package com.alibaba.otter.manager.biz.autoconfigure;

import com.alibaba.otter.manager.biz.autoconfigure.properties.ManagerProperties;
import com.alibaba.otter.manager.biz.config.canal.CanalService;
import com.alibaba.otter.manager.biz.config.channel.ChannelService;
import com.alibaba.otter.manager.biz.config.datamatrix.DataMatrixService;
import com.alibaba.otter.manager.biz.config.node.NodeService;
import com.alibaba.otter.manager.biz.monitor.PassiveMonitor;
import com.alibaba.otter.manager.biz.remote.ArbitrateRemoteService;
import com.alibaba.otter.manager.biz.remote.CanalRemoteService;
import com.alibaba.otter.manager.biz.remote.ConfigRemoteService;
import com.alibaba.otter.manager.biz.remote.StatsRemoteService;
import com.alibaba.otter.manager.biz.remote.impl.ArbitrateRemoteServiceImpl;
import com.alibaba.otter.manager.biz.remote.impl.CanalRemoteServiceImpl;
import com.alibaba.otter.manager.biz.remote.impl.ConfigRemoteServiceImpl;
import com.alibaba.otter.manager.biz.remote.impl.StatsRemoteServiceImpl;
import com.alibaba.otter.manager.biz.remote.interceptor.RemoteExceptionLoggerInterceptor;
import com.alibaba.otter.manager.biz.statistics.delay.DelayStatService;
import com.alibaba.otter.manager.biz.statistics.table.TableStatService;
import com.alibaba.otter.manager.biz.statistics.throughput.ThroughputStatService;
import com.alibaba.otter.shared.arbitrate.ArbitrateManageService;
import com.alibaba.otter.shared.communication.core.CommunicationClient;
import com.alibaba.otter.shared.communication.core.impl.DefaultCommunicationClientImpl;
import com.alibaba.otter.shared.communication.core.impl.dubbo.DubboCommunicationConnectionFactory;
import com.alibaba.otter.shared.communication.core.impl.dubbo.DubboCommunicationEndpoint;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class ManagerRemoteConfiguration {

    private final ManagerProperties managerProperties;

    public ManagerRemoteConfiguration(ManagerProperties managerProperties) {
        this.managerProperties = managerProperties;
    }

    /**
     *
     */
    @Bean(initMethod = "initial", destroyMethod = "destroy")
    public DubboCommunicationEndpoint endpoint() {
        DubboCommunicationEndpoint dubboCommunicationEndpoint = new DubboCommunicationEndpoint();
        dubboCommunicationEndpoint.setPayload(managerProperties.getCommunication().getPayload());
        dubboCommunicationEndpoint.setPort(managerProperties.getCommunication().getPort());
        return dubboCommunicationEndpoint;
    }

    /**
     *
     */
    @Bean(initMethod = "initial", destroyMethod = "destroy")
    public CommunicationClient communicationClient() {

        DefaultCommunicationClientImpl communicationClient = new DefaultCommunicationClientImpl();
        // 设置连接方式
        DubboCommunicationConnectionFactory dubboCommunicationConnectionFactory = new DubboCommunicationConnectionFactory();
        dubboCommunicationConnectionFactory.setPayload(managerProperties.getCommunication().getPayload());
        // 设置dubbo通讯方式
        communicationClient.setFactory(dubboCommunicationConnectionFactory);
        communicationClient.setPoolSize(managerProperties.getCommunication().getPoolSize());
        return communicationClient;
    }

    @Bean
    public RemoteExceptionLoggerInterceptor remoteExceptionLoggerInterceptor() {
        return new RemoteExceptionLoggerInterceptor();
    }


    @Bean
    public ConfigRemoteService configRemoteServiceTarget(ChannelService channelService,
                                                         NodeService nodeService,
                                                         DataMatrixService dataMatrixService) {

        ConfigRemoteServiceImpl configRemoteService = new ConfigRemoteServiceImpl();

        configRemoteService.setNodeService(nodeService);
        configRemoteService.setDataMatrixService(dataMatrixService);
        configRemoteService.setChannelService(channelService);

        return configRemoteService;
    }


    @Bean
    public ProxyFactoryBean configRemoteService(ConfigRemoteService configRemoteServiceTarget) {
        ProxyFactoryBean proxyFactoryBean = getLogInterceptorProxyBean();
        proxyFactoryBean.setTarget(configRemoteServiceTarget);
        return proxyFactoryBean;
    }

    @Bean
    public StatsRemoteService statsRemoteServiceTarget(DelayStatService delayStatService, TableStatService tableStatService, ThroughputStatService throughputStatService){
        StatsRemoteServiceImpl statsRemoteService = new StatsRemoteServiceImpl();
        statsRemoteService.setDelayStatService(delayStatService);
        statsRemoteService.setThroughputStatService(throughputStatService);
        statsRemoteService.setTableStatService(tableStatService);
        return statsRemoteService;
    }

    @Bean
    public ProxyFactoryBean statsRemoteService(StatsRemoteService statsRemoteServiceTarget) {
        ProxyFactoryBean proxyFactoryBean = getLogInterceptorProxyBean();
        proxyFactoryBean.setTarget(statsRemoteServiceTarget);
        return proxyFactoryBean;
    }

    @Bean
    public ArbitrateRemoteService arbitrateRemoteServiceTarget(ChannelService channelService,
                                                               ArbitrateManageService arbitrateManageService,
                                                               @Qualifier("exceptionRuleMonitor") PassiveMonitor exceptionRuleMonitor){
        ArbitrateRemoteServiceImpl arbitrateRemoteService = new ArbitrateRemoteServiceImpl();
        arbitrateRemoteService.setChannelService(channelService);
        arbitrateRemoteService.setArbitrateManageService(arbitrateManageService);
        arbitrateRemoteService.setExceptionRuleMonitor(exceptionRuleMonitor);
        return arbitrateRemoteService;
    }

    @Bean
    public ProxyFactoryBean arbitrateRemoteService(ArbitrateRemoteService arbitrateRemoteServiceTarget) {
        ProxyFactoryBean proxyFactoryBean = getLogInterceptorProxyBean();
        proxyFactoryBean.setTarget(arbitrateRemoteServiceTarget);
        return proxyFactoryBean;
    }

    @Bean
    public CanalRemoteService canalRemoteServiceTarget(CanalService canalService){
        CanalRemoteServiceImpl canalRemoteService = new CanalRemoteServiceImpl();
        canalRemoteService.setCanalService(canalService);
        canalRemoteService.setTsdbJdbcUrl(managerProperties.getDatabase().getUrl());
        canalRemoteService.setTsdbJdbcUserName(managerProperties.getDatabase().getUsername());
        canalRemoteService.setTsdbJdbcPassword(managerProperties.getDatabase().getPassword());
        return canalRemoteService;
    }

    @Bean
    public ProxyFactoryBean canalRemoteService(CanalRemoteService canalRemoteServiceTarget) {
        ProxyFactoryBean proxyFactoryBean = getLogInterceptorProxyBean();
        proxyFactoryBean.setTarget(canalRemoteServiceTarget);
        return proxyFactoryBean;
    }

    private ProxyFactoryBean getLogInterceptorProxyBean() {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        proxyFactoryBean.setProxyTargetClass(true);
        proxyFactoryBean.setInterceptorNames("remoteExceptionLoggerInterceptor");
        return proxyFactoryBean;
    }


}
